import { Box3, MathUtils, Sphere, Vector3 } from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { _SceneManager } from '.';
import { _Config } from './Config';
import { _Renderer } from './Renderer';
import Scene from './Scene';
class Control {
  private cameraController: OrbitControls;
  private scene: Scene;
  private readonly fouceTime = 0.5;
  /**
   * init
   */
  public init(scene: Scene): void {
    this.scene = scene;
    if (!this.cameraController) {
      this.cameraController = new OrbitControls(
        scene.worldCamera,
        _Config.canvasDom
      );

      this.cameraController.minPolarAngle = MathUtils.degToRad(10);
      this.cameraController.maxPolarAngle = MathUtils.degToRad(80);
      this.cameraController.enablePan = false;
      this.cameraController.enableDamping = false;
      this.cameraController.dampingFactor = 0.1;
      this.cameraController.addEventListener('change', () => {
        _Renderer.setDirty();
      });
    }
  }
  /**
   * changeCameraState
   */
  public changeCameraState(cameraPos: Vector3, target?: Vector3) {
    if (this.cameraController) {
      this.cameraController.object.position.copy(cameraPos);
      if (target) {
        this.cameraController.target.copy(target);
      }
      this.cameraController.update();
    }
  }
  private box: Box3;
  private sphere: Sphere;
  private currentCameraPos: Vector3;
  /**
   * focusToScene
   */
  public focusToScene() {
    if (!this.box) {
      this.box = new Box3();
    }
    this.box.makeEmpty();
    this.box.expandByObject(this.scene.currentNode);
    if (!this.sphere) {
      this.sphere = new Sphere();
    }
    this.box.getBoundingSphere(this.sphere);
    let tagetPos = this.cameraController.object.position
      .clone()
      .sub(this.sphere.center)
      .setLength(this.sphere.radius * 2)
      .add(this.sphere.center);
    let current = 0;
    this.currentCameraPos = this.cameraController.object.position.clone();
    _SceneManager.addFrameEvent('focusToTarget', (offset) => {
      current += offset;
      const lerp = current / this.fouceTime;
      this.currentCameraPos.lerp(tagetPos, lerp);
      this.changeCameraState(this.currentCameraPos, this.sphere.center);
      _Renderer.setDirty();
      return lerp >= 1;
    });
    this.cameraController.minDistance = this.sphere.radius;
    this.cameraController.maxDistance = this.sphere.radius * 3;

  }
}
export const _Control = new Control();
